package com.xbongbong.paas.script.controller;

import com.alibaba.fastjson.JSON;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.pojo.dto.CustomerRuleDeletePublicTagDTO;
import com.xbongbong.paas.pojo.dto.PaymentSheetDataDTO;
import com.xbongbong.paas.pojo.dto.ReturnCustomer2PublicAsyncDTO;
import com.xbongbong.paas.pojo.dto.ReturnCustomer2PublicDTO;
import com.xbongbong.paas.pojo.vo.ReturnCustomer2PublicVO;
import com.xbongbong.paas.service.TransferBackRuleScriptService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.enums.ClueSeniorRuleTypeEnum;
import com.xbongbong.saas.enums.CustomerSeniorRuleTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.TransferBackRuleSeniorModel;
import com.xbongbong.sys.domain.entity.RoleEntity;
import com.xbongbong.sys.model.RoleModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author yanglei
 * @ProjectName xbb-web-script
 * @Description: 公海池高级模式规则定时脚本
 * @date 2022/4/13
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/script/publicSeniorRule")
public class TransferBackRuleScriptController {

    private static final Logger LOG = LoggerFactory.getLogger(TransferBackRuleScriptController.class);


    @Resource
    private TransferBackRuleScriptService transferBackRuleScriptService;
    @Resource
    private TransferBackRuleSeniorModel transferBackRuleSeniorModel;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private RoleModel roleModel;

    /**
     * 客户公海高级模式退回规则定时脚本
     * @param returnCustomer2PublicDTO
     * @param br
     * @return
     * 创建时间 2022/4/13 10:53 PM
     * 修改时间 2019/4/13 10:53 PM
     * @author yanglei
     * @since v1.0
     * @version v1.0
     */
    @RequestMapping(value = "/returnCustomer2PublicSenior", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String returnCustomer2PublicSenior(@Valid ReturnCustomer2PublicDTO returnCustomer2PublicDTO, BindingResult br) {
        XbbResponse<ReturnCustomer2PublicVO> response;
        try {
            response = returnCustomer2PublicSenior(returnCustomer2PublicDTO);
        } catch (XbbException e) {
            response = new XbbResponse<>(e);
        }
        return JSON.toJSONString(response);
    }


    public XbbResponse<ReturnCustomer2PublicVO> returnCustomer2PublicSenior(ReturnCustomer2PublicDTO returnCustomer2PublicDTO) throws XbbException {

        ReturnCustomer2PublicVO returnCustomer2PublicVO = new ReturnCustomer2PublicVO();

        ReturnCustomer2PublicAsyncDTO returnCustomer2PublicAsyncDTO = transferBackRuleScriptService.verifyParam(returnCustomer2PublicDTO);

        String corpid = returnCustomer2PublicDTO.getCorpid();

        Boolean back = returnCustomer2PublicAsyncDTO.getBack();
        Boolean notify = returnCustomer2PublicAsyncDTO.getNotify();

        if (!notify && !back) {
            LOG.warn("既不需要消息提醒又不用退回公海池规则没有执行必要，停止定时任务！");
            return new XbbResponse<>(returnCustomer2PublicVO);
        }

        if (StringUtil.isNotEmpty(corpid)) {
            //单个公司执行判断是否开启客户公海高级模式
            boolean customerPublicPoolSeniorModel = commonHelp.isCustomerPublicPoolSeniorModel(corpid);
            if (!customerPublicPoolSeniorModel){
                LOG.warn("该公司未开启客户公海高级模式，停止执行任务！");
                return new XbbResponse<>(returnCustomer2PublicVO);
            }
            transferBackRuleScriptService.returnCustomer2PublicSeniorAsync(returnCustomer2PublicAsyncDTO);
        } else {
            Long now = DateTimeUtil.getInt();
            Integer pageSize = 100;

            String startCorpid = null;
            List<String> corpids = transferBackRuleSeniorModel.getSeniorRuleCorpidList(now,startCorpid, pageSize, CustomerSeniorRuleTypeEnum.BACK_RULE.getCode(),XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());

            while (Objects.nonNull(corpids) && !corpids.isEmpty()) {
                returnCustomer2PublicAsyncDTO.setCorpids(corpids);
                transferBackRuleScriptService.returnCustomer2PublicSeniorAsync(returnCustomer2PublicAsyncDTO);
                startCorpid = corpids.get(corpids.size() - 1);
                corpids = transferBackRuleSeniorModel.getSeniorRuleCorpidList(now,startCorpid, pageSize,CustomerSeniorRuleTypeEnum.BACK_RULE.getCode(),XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
            }
        }
        return new XbbResponse<>(returnCustomer2PublicVO);
    }



    /**
     * 线索公海高级模式退回规则定时脚本
     * @param returnCustomer2PublicDTO
     * @param br
     * @return
     * 创建时间 2022/5/9 10:53 PM
     * 修改时间 2019/5/9 10:53 PM
     * @author yanglei
     * @since v1.0
     * @version v1.0
     */
    @RequestMapping(value = "/returnClue2PublicSenior", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String returnClue2PublicSenior(@Valid ReturnCustomer2PublicDTO returnCustomer2PublicDTO, BindingResult br) {
        XbbResponse<ReturnCustomer2PublicVO> response;
        try {
            response = returnClue2PublicSenior(returnCustomer2PublicDTO);
        } catch (XbbException e) {
            response = new XbbResponse<>(e);
        }
        return JSON.toJSONString(response);
    }


    public XbbResponse<ReturnCustomer2PublicVO> returnClue2PublicSenior(ReturnCustomer2PublicDTO returnCustomer2PublicDTO) throws XbbException {

        ReturnCustomer2PublicVO returnCustomer2PublicVO = new ReturnCustomer2PublicVO();

        ReturnCustomer2PublicAsyncDTO returnCustomer2PublicAsyncDTO = transferBackRuleScriptService.verifyParam(returnCustomer2PublicDTO);

        String corpid = returnCustomer2PublicDTO.getCorpid();
        Boolean back = returnCustomer2PublicAsyncDTO.getBack();
        Boolean notify = returnCustomer2PublicAsyncDTO.getNotify();

        if (!notify && !back) {
            LOG.warn("既不需要消息提醒又不用退回公海池规则没有执行必要，停止定时任务！");
            return new XbbResponse<>(returnCustomer2PublicVO);
        }

        if (StringUtil.isNotEmpty(corpid)) {
            //单个公司执行判断是否开启线索公海高级模式
            boolean cluePublicPoolSeniorModel = commonHelp.isCluePublicPoolSeniorModel(corpid);
            if (!cluePublicPoolSeniorModel){
                LOG.warn("该公司未开启线索高级模式，停止执行任务！");
                return new XbbResponse<>(returnCustomer2PublicVO);
            }
            transferBackRuleScriptService.returnClue2PublicSeniorAsync(returnCustomer2PublicAsyncDTO);
        } else {
            Long now = DateTimeUtil.getInt();
            // 每个线程的最大公司处理数
            Integer pageSize = 100;

            String startCorpid = null;
            List<String> corpids = transferBackRuleSeniorModel.getSeniorRuleCorpidList(now,startCorpid, pageSize, ClueSeniorRuleTypeEnum.BACK_RULE.getCode(), XbbRefTypeEnum.CLUE.getCode());

            while (Objects.nonNull(corpids) && !corpids.isEmpty()) {
                returnCustomer2PublicAsyncDTO.setCorpids(corpids);
                transferBackRuleScriptService.returnClue2PublicSeniorAsync(returnCustomer2PublicAsyncDTO);
                startCorpid = corpids.get(corpids.size() - 1);
                corpids = transferBackRuleSeniorModel.getSeniorRuleCorpidList(now,startCorpid, pageSize,ClueSeniorRuleTypeEnum.BACK_RULE.getCode(),XbbRefTypeEnum.CLUE.getCode());
            }
        }
        return new XbbResponse<>(returnCustomer2PublicVO);
    }

    /**
     * 客户公海高级模式转移规则定时脚本
     * @param returnCustomer2PublicDTO
     * @param br
     * @return
     * 创建时间 2022/5/9 10:53 PM
     * 修改时间 2019/5/9 10:53 PM
     * @author yanglei
     * @since v1.0
     * @version v1.0
     */
    @RequestMapping(value = "/transferCustomer2PublicSenior", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String transferCustomer2PublicSenior(@Valid ReturnCustomer2PublicDTO returnCustomer2PublicDTO, BindingResult br) {
        XbbResponse<ReturnCustomer2PublicVO> response;
        try {
            response = transferCustomer2PublicSenior(returnCustomer2PublicDTO);
        } catch (XbbException e) {
            response = new XbbResponse<>(e);
        }
        return JSON.toJSONString(response);
    }


    public XbbResponse<ReturnCustomer2PublicVO> transferCustomer2PublicSenior(ReturnCustomer2PublicDTO returnCustomer2PublicDTO) throws XbbException {

        ReturnCustomer2PublicVO returnCustomer2PublicVO = new ReturnCustomer2PublicVO();

        ReturnCustomer2PublicAsyncDTO returnCustomer2PublicAsyncDTO = transferBackRuleScriptService.verifyParam(returnCustomer2PublicDTO);

        String corpid = returnCustomer2PublicDTO.getCorpid();
        Boolean transfer = returnCustomer2PublicAsyncDTO.getTransfer();
        Boolean notify = returnCustomer2PublicAsyncDTO.getNotify();

        if (!notify && !transfer) {
            LOG.warn("既不需要消息提醒又不用转移公海池规则没有执行必要，停止定时任务！");
            return new XbbResponse<>(returnCustomer2PublicVO);
        }

        if (StringUtil.isNotEmpty(corpid)) {
            //单个公司执行判断是否开启客户公海高级模式
            boolean customerPublicPoolSeniorModel = commonHelp.isCustomerPublicPoolSeniorModel(corpid);
            if (!customerPublicPoolSeniorModel){
                LOG.warn("该公司未开启客户公海高级模式，停止执行任务！");
                return new XbbResponse<>(returnCustomer2PublicVO);
            }
            transferBackRuleScriptService.transferCustomer2PublicSeniorAsync(returnCustomer2PublicAsyncDTO);
        } else {
            Long now = DateTimeUtil.getInt();
            // 每个线程的最大公司处理数
            Integer pageSize = 100;

            String startCorpid = null;
            List<String> corpids = transferBackRuleSeniorModel.getSeniorRuleCorpidList(now,startCorpid, pageSize,CustomerSeniorRuleTypeEnum.TRANSFER_RULE.getCode(),XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());

            while (Objects.nonNull(corpids) && !corpids.isEmpty()) {
                returnCustomer2PublicAsyncDTO.setCorpids(corpids);
                transferBackRuleScriptService.transferCustomer2PublicSeniorAsync(returnCustomer2PublicAsyncDTO);
                startCorpid = corpids.get(corpids.size() - 1);
                corpids = transferBackRuleSeniorModel.getSeniorRuleCorpidList(now,startCorpid, pageSize,CustomerSeniorRuleTypeEnum.TRANSFER_RULE.getCode(),XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
            }
        }
        return new XbbResponse<>(returnCustomer2PublicVO);
    }

    /**
     * 线索公海高级模式转移规则定时脚本
     * @param returnCustomer2PublicDTO
     * @param br
     * @return
     * 创建时间 2022/5/9 10:53 PM
     * 修改时间 2019/5/9 10:53 PM
     * @author yanglei
     * @since v1.0
     * @version v1.0
     */
    @RequestMapping(value = "/transferClue2PublicSenior", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String transferClue2PublicSenior(@Valid ReturnCustomer2PublicDTO returnCustomer2PublicDTO, BindingResult br) {
        XbbResponse<ReturnCustomer2PublicVO> response;
        try {
            response = transferClue2PublicSenior(returnCustomer2PublicDTO);
        } catch (XbbException e) {
            response = new XbbResponse<>(e);
        }
        return JSON.toJSONString(response);
    }


    public XbbResponse<ReturnCustomer2PublicVO> transferClue2PublicSenior(ReturnCustomer2PublicDTO returnCustomer2PublicDTO) throws XbbException {

        ReturnCustomer2PublicVO returnCustomer2PublicVO = new ReturnCustomer2PublicVO();

        ReturnCustomer2PublicAsyncDTO returnCustomer2PublicAsyncDTO = transferBackRuleScriptService.verifyParam(returnCustomer2PublicDTO);

        String corpid = returnCustomer2PublicDTO.getCorpid();
        Boolean transfer = returnCustomer2PublicAsyncDTO.getTransfer();
        Boolean notify = returnCustomer2PublicAsyncDTO.getNotify();

        if (!notify && !transfer) {
            LOG.warn("既不需要消息提醒又不用转移公海池规则没有执行必要，停止定时任务！");
            return new XbbResponse<>(returnCustomer2PublicVO);
        }

        if (StringUtil.isNotEmpty(corpid)) {
            //单个公司执行判断是否开启线索公海高级模式
            boolean cluePublicPoolSeniorModel = commonHelp.isCluePublicPoolSeniorModel(corpid);
            if (!cluePublicPoolSeniorModel){
                LOG.warn("该公司未开启线索高级模式，停止执行任务！");
                return new XbbResponse<>(returnCustomer2PublicVO);
            }
            transferBackRuleScriptService.transferClue2PublicSeniorAsync(returnCustomer2PublicAsyncDTO);
        } else {
            Long now = DateTimeUtil.getInt();
            // 每个线程的最大公司处理数
            Integer pageSize = 100;

            String startCorpid = null;
            List<String> corpids = transferBackRuleSeniorModel.getSeniorRuleCorpidList(now,startCorpid, pageSize,ClueSeniorRuleTypeEnum.TRANSFER_RULE.getCode(),XbbRefTypeEnum.CLUE.getCode());

            while (Objects.nonNull(corpids) && !corpids.isEmpty()) {
                returnCustomer2PublicAsyncDTO.setCorpids(corpids);
                transferBackRuleScriptService.transferClue2PublicSeniorAsync(returnCustomer2PublicAsyncDTO);
                startCorpid = corpids.get(corpids.size() - 1);
                corpids = transferBackRuleSeniorModel.getSeniorRuleCorpidList(now,startCorpid, pageSize,ClueSeniorRuleTypeEnum.TRANSFER_RULE.getCode(),XbbRefTypeEnum.CLUE.getCode());
            }
        }
        return new XbbResponse<>(returnCustomer2PublicVO);
    }

    /**
     * 删除已有的权限 公海池规则 (121)和公海池分组(247)
     * 已经拥有这个两个权限之一的角色将添加新的权限 - 客户公海池(1203)  (1204)
     * @param paymentSheetDataDTO
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/updateOtherSetPublicPermission", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String updateOtherSetPublicPermission(@RequestBody @Valid PaymentSheetDataDTO paymentSheetDataDTO)  {
        try {
            if (!proBaseConfig.getXbbCode().equals(paymentSheetDataDTO.getXbbCode())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
            }
            LOG.warn("-----------updateOtherSetPublicPermission start 开始执行更新公海池权限脚本-----------");
            long timeStart = DateTimeUtil.getInt();
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            String roleColumns = "id, permissions";
            Integer start = 0;
            Integer pageNum = 500;
            Integer idGte = 0;
            params.put("del", DelEnum.NORMAL.getDel());
            Long maxId = roleModel.getMaxId(params);
            params.put("columns", roleColumns);
            params.put("start", start);
            params.put("pageNum", pageNum);
            params.put("orderByStr", "id asc");
            int i = 0;
            while (true){
                params.put("idGte", idGte);
                LOG.warn("处理进度：已处理到 tb_role.id " + idGte + " / " + maxId);
                List<RoleEntity> allRole = roleModel.findAllRoleByCorpid(params);
                if (CollectionsUtil.isEmpty(allRole)){
                    break;
                }
                idGte = allRole.get(allRole.size() - 1).getId();

                Iterator<RoleEntity> iterator = allRole.iterator();
                while (iterator.hasNext()){
                    RoleEntity role = iterator.next();
                    Set<Integer> permissionIdsSet = role.getPermissionIdsSet();
                    // 如果该角色有公海池规则的权限，先把他去掉，再添加线索公海池和客户公海池的权限
                    if (permissionIdsSet.contains(121)){
                        //permissionIdsSet.remove(121);
                        permissionIdsSet.add(1203);
                        permissionIdsSet.add(1204);
                    }
                    // 如果该角色有公海池分组的权限，先把他去掉，再添加线索公海池和客户公海池的权限
                    if(permissionIdsSet.contains(247)){
                        //permissionIdsSet.remove(247);
                        permissionIdsSet.add(1203);
                        permissionIdsSet.add(1204);
                    }
                    String permissionIdsStr = StringUtil.arrayToString(permissionIdsSet.toArray(), "|");
                    role.setPermissions(permissionIdsStr);
                }
                if (CollectionsUtil.isNotEmpty(allRole)){
                    roleModel.updateBatchAll(allRole);
                }
            }
            LOG.warn("-----------time consume updateOtherSetPublicPermission:" + (DateTimeUtil.getInt() - timeStart));
            LOG.warn("-----------公海池权限更新成功-----------");
        } catch (Exception e) {
            LOG.error("updateOtherSetPublicPermission", e);
        }
        return JSON.toJSONString("{\"msg\":\"success\"}");
    }


    /**
     * 公海高级模式 - 动态更新客户和线索 退字 标签
     * @param ruleDeleteTagDTO
     * @param br
     * @return
     */
    @RequestMapping(value = "/deletePublicSeniorTag", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String deletePublicSeniorTag(@RequestBody @Valid CustomerRuleDeletePublicTagDTO ruleDeleteTagDTO, BindingResult br) {
        XbbResponse<BaseVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                transferBackRuleScriptService.deletePublicSeniorTag(ruleDeleteTagDTO.getCorpid(),ruleDeleteTagDTO.getCustomerIds(),ruleDeleteTagDTO.getBusinessType(),ruleDeleteTagDTO.getFormId());
                response = new XbbResponse<>(new BaseVO());
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }
}
